package com.zy;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ServerApp
{

    public static int DEFAULT_PORT=8083;
    private static final int MASTER_REACTOR_SIZE = 1;
    private static final int SLAVE_REACTOR_SIZE = Runtime.getRuntime().availableProcessors();
    private static final int BUSINESS_THREAD_SIZE = Runtime.getRuntime().availableProcessors() * 2;
    //日志
    private static final Logger logger= LoggerFactory.getLogger(ServerApp.class);

    // java -jar xxx.jar 8083
    public static void main( String[] args )
    {
        int port;
        try {
            port = Integer.parseInt(args[0]);
        }catch(Exception ex){
            port = DEFAULT_PORT;
        }

        //主reactor线程组(处理连接请求)
        EventLoopGroup masterReactorGroup = new NioEventLoopGroup(MASTER_REACTOR_SIZE);
        //从reactor线程组(处理IO请求)
        EventLoopGroup slaveReactorGroup = new NioEventLoopGroup(SLAVE_REACTOR_SIZE);
        // 业务线程组(处理业务逻辑)
        EventLoopGroup businessGroup = new NioEventLoopGroup(BUSINESS_THREAD_SIZE);

       try {
           //启动器
           ServerBootstrap serverBootstrap = new ServerBootstrap();
           serverBootstrap.group(masterReactorGroup, slaveReactorGroup)  //****关键点:  主从reactor线程组
                   .channel(NioServerSocketChannel.class)  //channel通道 类型    NioServerSocketChannel  基于nio的通道
                   //主reactor配置项
                   .option(ChannelOption.SO_BACKLOG, 1024)    //联接队列的大小
                   .option(ChannelOption.SO_REUSEADDR, true)  //端口复用
                   //从reactor配置项
                   .childOption(ChannelOption.SO_KEEPALIVE, true)   //保持连接
                   .childOption(ChannelOption.TCP_NODELAY, true)    //关闭延迟发送

                   .handler(new LoggingHandler(LogLevel.INFO))   //通过channel配置日志处理器，并指定了日志级别
                   .childHandler(new MinotorServerInitializer(businessGroup));

           ChannelFuture future = serverBootstrap.bind(port).sync();  // 绑定端口

           logger.info("http server 启动，监听端口:" + port);

           future.channel().closeFuture().sync();  // 关闭通道
       }catch(Exception ex){
           logger.error(  "服务端异常: {}", ex );
       }finally{
           masterReactorGroup.shutdownGracefully();
           slaveReactorGroup.shutdownGracefully();
           businessGroup.shutdownGracefully();
       }
    }
}
